# -*- coding: utf-8 -*-
import random
import urwid


palette = [
    ('normal', 'light gray', 'default'),
    ('active', 'light green', 'default'),
    ('flag', 'light red', 'default'),
    ('bomb', 'light red', 'default', 'bold'),
]


class Element(object):
    default_view = {'hided': ('normal', ' * '), 'flag': ('flag', ' X '), 'bomb': ('bomb', ' @ ')}

    def __init__(self):
        self.clicked = False
        self.has_flag = False
        self.is_bomb = False
        self.hint = -1


class Board(object):
    num_rows = 15
    num_cols = 15
    num_mines = 21

    def __init__(self):
        self.focus = [self.num_rows/2, self.num_cols/2]
        self.remaining = 0
        self.mines = self.num_mines
        self.flags = 0
        self.elements = []
        self.reset()

    def on_board(self, row, col):
        return all([row >= 0, col >= 0, row < self.num_rows, col < self.num_cols])

    def _element(self, row, col):
        if self.on_board(row, col):
            return self.elements[self.num_rows * row + col]

    def scan_hint(self, row, col):
        hint = 0
        for c in (col - 1, col, col + 1):
            for r in (row - 1, row, row + 1):
                e = self._element(r, c)
                if e is not None and e.is_bomb:
                    hint += 1
        return hint

    def focus_move(self, key):
        if key == 'left':
            if self.focus[0] > 0:
                self.focus[0] -= 1
        elif key == 'right':
            if self.focus[0] < self.num_cols:
                self.focus[0] += 1
        elif key == 'up':
            if self.focus[1] < self.num_cols:
                self.focus[1] += 1
        elif key == 'down':
            if self.focus[1] > 0:
                self.focus[1] -= 1

    def render(self):
        data = [e.view() for e in self.elements]
        data = [data[i:i+self.num_rows] for i in xrange(0, len(data), self.num_rows)]

    def show(self):
        for e in self.elements:
            e.clicked = True
        return self.render()

    def reset(self):
        self.elements = [Element() for i in xrange(self.num_rows * self.num_cols)]
        mines = self.mines
        self.remaining = self.num_rows * self.num_cols - mines
        # 布雷
        while mines > 0:
            col = random.randint(0, self.num_cols - 1)
            row = random.randint(0, self.num_rows - 1)
            e = self._element(row, col)
            if e is not None and not e.is_bomb:
                e.is_bomb = True
                mines -= 1
        # 计算每个点的雷数量
        for row in xrange(self.num_rows):
            for col in xrange(self.num_cols):
                e = self._element(row, col)
                if e is not None and not e.is_bomb:
                    e.hint = self.scan_hint(row, col)

    def set_flag(self):
        e = self._element(*self.focus)
        e.flag = True
        e.clicked = True


    def enter(self):
        e = self._element(*self.focus)


def handler(key):
    if key == 'enter':
        board.enter()
    elif key == ' ':
        pass
    elif key in ('left', 'right', 'up', 'down'):
        board.focus_move(key)
    elif key in ('q', 'Q'):
        raise urwid.ExitMainLoop()
    else:
        pass

board = Board()
txt = urwid.Text(u'', align='center')
txt.set_text(('active', board.render()))
fill = urwid.Filler(txt)
loop = urwid.MainLoop(fill, palette, unhandled_input=handler)
loop.run()
